package com.iwayin.core.bo.ask;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.iwayin.core.bo.BaseBO;
import com.iwayin.core.bo.answer.AnswerBO;
import com.iwayin.core.bo.comment.CommentBO;
import com.iwayin.core.common.Constants;
import com.iwayin.core.common.HistoryInfoUtil;
import com.iwayin.core.dao.answer.AnswerDAO;
import com.iwayin.core.dao.ask.AskDAO;
import com.iwayin.core.dao.comment.CommentDAO;
import com.iwayin.core.dao.follow.FollowDAO;
import com.iwayin.core.dao.like.LikeDAO;
import com.iwayin.core.dao.user.UserDAO;
import com.iwayin.core.dao.vote.AnswerVoteDAO;
import com.iwayin.core.dataobject.AnswerDO;
import com.iwayin.core.dataobject.AnswerVoteDO;
import com.iwayin.core.dataobject.AskDO;
import com.iwayin.core.dataobject.CommentDO;
import com.iwayin.core.dataobject.UserDO;
import com.iwayin.core.utils.UpYun;
import com.iwayin.core.utils.UtilCommon;
import com.iwayin.core.utils.exception.BOException;
import com.iwayin.core.vo.SearchVO;

public class AskBOImpl extends BaseBO implements AskBO {

	private AskDAO askDAO;
	private UserDAO userDAO;
	private FollowDAO followDAO;
	private CommentDAO commentDAO;
	private AnswerDAO answerDAO;
	private AnswerVoteDAO answerVoteDAO;
	private LikeDAO likeDAO;

	private AnswerBO answerBO;
	private CommentBO commentBO;

	@Override
	public Long addAsk(AskDO ask) {
		Long askId = null;
		try {
			ask.setStatus(1L);
			if (ask.getPicPath().endsWith("!small")) {
				String originalPicPath = ask.getPicPath().substring(0, ask.getPicPath().length() - 6);
				ask.setOriginalPicPath(originalPicPath);
				ask.setPicPath(originalPicPath);
			} else {
				String newFileName = UtilCommon.buildNewFileName(ask.getPicPath()); // 获取保存文件名称
				URL url = new URL(ask.getPicPath());
				URLConnection u = url.openConnection();
				u.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
				DataInputStream in = new DataInputStream(u.getInputStream());
				String tempSavePath = ask.getTempPicPath() + "/" + newFileName;
				File picFile = new File(tempSavePath);
				DataOutputStream dos = new DataOutputStream(new FileOutputStream(picFile));
				byte[] buffer = new byte[4096];
				int count = 0;
				while ((count = in.read(buffer)) > 0) {
					dos.write(buffer, 0, count);
				}
				dos.close();/* 后面三行为关闭输入输出流以及网络资源的固定格式 */
				in.close();
				UpYun upyun = new UpYun(Constants.ASK_IMG_BUCKET, Constants.ASK_IMG_USERNAME, Constants.ASK_IMG_PASSWORD);
				upyun.writeFile("/" + newFileName, picFile);
				String imageUrl = Constants.ASK_IMG_DOMAIN + newFileName;
				ask.setPicPath(imageUrl);
				ask.setOriginalPicPath(imageUrl);
			}
			askId = this.askDAO.addAsk(ask);
			// 用户ask count +1
			if (askId != null) {
				userDAO.askCountPlusOne(ask.getUserId());
			}
		} catch (Exception e) {
			loger.error("AskBO.addAsk", e);
			throw new BOException("系统异常");
		}
		return askId;
	}

	@Override
	public void deleteAsk(AskDO ask) {
		AskDO existObj = askDAO.getAskById(ask.getId());
		// 数据合法性校验
		if (existObj == null) {
			throw new BOException("此问问不存在，请刷新页面");
		}
		if (!existObj.getUserId().equals(ask.getUserId())) {
			throw new BOException("你无权删除别人问问");
		}
		try {
			askDAO.deleteAskById(ask);
			// 删除answer
			answerDAO.deleteAnswerByAskId(ask.getId());
			// 删除投票
			answerVoteDAO.deleteVoteByAskId(ask.getId());
			// 删除评论
			// TODO
			commentDAO.deleteCommentByAskId(ask.getId());
			// 删除like记录
			// TODO
			// 问问数-1
			userDAO.askCountminuOne(ask.getUserId());
		} catch (Exception e) {

		}
	}

	@Override
	public List<UserDO> findHotAskUser(AskDO ask) {
		List<Long> hotAskUserIdList = this.askDAO.findHotAskUserId(ask);
		List<UserDO> hotAskUserList = new ArrayList<UserDO>(hotAskUserIdList.size());
		for (Long userId : hotAskUserIdList) {
			UserDO hotUser = this.userDAO.getUserById(userId);
			hotAskUserList.add(hotUser);
		}
		return hotAskUserList;
	}

	@Override
	public List<AskDO> findFollowAsk(AskDO ask) {
		List<Long> followIdList = this.followDAO.findAllFollowByUserId(ask.getUserId());
		ask.setFollowIdList(followIdList);
		List<AskDO> askList = this.askDAO.findFollowAak(ask);
		return padAsk(askList, ask.getUserId());
	}

	@Override
	public List<SearchVO> searchAsks(SearchVO query) {
		List<SearchVO> askList = this.askDAO.searchAsks(query);
		return askList;
	}

	@Override
	public List<AskDO> findHotAsk(AskDO ask) {
		List<AskDO> asks = this.askDAO.findHotAskList(ask);
		return padAsk(asks, ask.getUserId());
	}

	@Override
	public List<AskDO> findNoLoginLastestAsk(AskDO ask) {
		List<AskDO> asks = this.askDAO.findLastestAsk(ask);
		return padNoLoginAsk(asks);
	}
	@Override
	public List<AskDO> findNoLoginUserAsk(AskDO ask) {
		List<AskDO> asks = this.askDAO.findUserAsks(ask);
		return padNoLoginAsk(asks);
	}
	@Override
	public List<AskDO> findLastestAsk(AskDO ask) {
		List<AskDO> asks = this.askDAO.findLastestAsk(ask);
		return padAsk(asks, ask.getUserId());
	}

	@Override
	public List<AskDO> findUserAsks(AskDO ask) {
		List<AskDO> asks = this.askDAO.findUserAsks(ask);
		return padAsk(asks, ask.getLoginId());
	}

	private List<AskDO> padAsk(List<AskDO> asks, Long myId) {
		List<AskDO> userAsks = new ArrayList<AskDO>();
		HashMap<Long, UserDO> userMap = new HashMap<Long, UserDO>();
		if (asks != null) {
			for (AskDO ask : asks) {
				UserDO u = userMap.get(ask.getUserId());
				if (u == null) {
					u = this.userDAO.getUserById(ask.getUserId());
					userMap.put(u.getId(), u);
				}
				padLastestComment(ask);//lastestComment
				pasUserInfo(ask,u);//userInfo 
				
				AnswerDO answerQuery = new AnswerDO();
				answerQuery.setAskId(ask.getId());
				List<AnswerDO> answerList = this.answerBO.findAnswers(answerQuery, myId);
				ask.setIsAnswer(answerQuery.getIsAnswer());
				ask.setAnswerList(answerList);
				
				boolean isLike = likeDAO.isLike(ask.getId(),myId);
				ask.setIsLike(isLike);
				
				userAsks.add(ask);
			}
		}
		return userAsks;
	}

	private AskDO padLastestComment(AskDO ask){
		CommentDO lastestComment = this.commentDAO.findLatestComment(ask.getId());
		if (lastestComment != null) {
			UserDO user = this.userDAO.getUserById(lastestComment.getUserId());
			if(user!=null){
				lastestComment.setCommentUserName(user.getLoginName());
				ask.setLastestComment(lastestComment);
			}
		}
		return ask;
	}
	
	private AskDO pasUserInfo(AskDO ask,UserDO user){
		ask.setUserName(user.getNickname());
		ask.setAvatarPath(user.getAvatarPath());
		ask.setHistoryInfo(HistoryInfoUtil.getHistoryInfo(ask.getCreateTime()));
		return ask;
	}
	

	private List<AskDO> padNoLoginAsk(List<AskDO> asks) {
		List<AskDO> userAsks = new ArrayList<AskDO>();
		HashMap<Long, UserDO> userMap = new HashMap<Long, UserDO>();
		if (asks != null) {
			for (AskDO ask : asks) {
				ask = this.askDAO.findAskByAskId(ask.getId());
				UserDO u = userMap.get(ask.getUserId());
				if (u == null) {
					u = this.userDAO.getUserById(ask.getUserId());
					userMap.put(u.getId(), u);
				}
				
				padLastestComment(ask);//lastestComment
				pasUserInfo(ask,u);//userInfo 
				
				//answer
				AnswerDO answerQuery = new AnswerDO();
				answerQuery.setAskId(ask.getId());
				List<AnswerDO> answerList = this.answerBO.findAnswers(answerQuery);
				ask.setAnswerList(answerList);
				ask.setIsLike(false);
				userAsks.add(ask);
			}
		}
		return userAsks;
	}

	@Override
	public List<UserDO> findAskMostToday(Long size) {
		List<AskDO> asks = askDAO.findAskMostToday(size);
		List<UserDO> users = new ArrayList<UserDO>();
		if (asks != null && asks.size() > 0) {
			for (AskDO ask : asks) {
				UserDO user = this.userDAO.getUserById(ask.getUserId());
				user.setAskCountToday(ask.getAskCountToday());
				users.add(user);
			}
		}
		return users;
	}

	@Override
	public AskDO askDetails(Long askId, Long userId) {
		AskDO ask = this.askDAO.getAskById(askId);
		UserDO user = this.userDAO.getUserById(ask.getUserId());

		pasUserInfo(ask,user);

		// pad answers isanswer
		AnswerDO answerQuery = new AnswerDO();
		answerQuery.setAskId(ask.getId());
		List<AnswerDO> answerList = this.answerBO.findAnswers(answerQuery, userId);
		ask.setIsAnswer(answerQuery.getIsAnswer());

		boolean isLike = likeDAO.isLike(ask.getId(),userId);
		ask.setIsLike(isLike);
		
		ask.setAnswerList(answerList);
		return ask;
	}

	@Override
	public AskDO askDetails(Long askId) {
		AskDO ask = this.askDAO.getAskById(askId);
		UserDO user = this.userDAO.getUserById(ask.getUserId());

		pasUserInfo(ask,user);

		// pad answers isanswer
		AnswerDO answerQuery = new AnswerDO();
		answerQuery.setAskId(askId);
		List<AnswerDO> answerList = this.answerBO.findAnswers(answerQuery);
		ask.setAnswerList(answerList);

		// pad comments
		CommentDO commentQuery = new CommentDO();
		commentQuery.setAskId(askId);
		List<CommentDO> comments = commentBO.findAskComments(commentQuery);
		ask.setCommentList(comments);
		
		return ask;
	}

	@Override
	public List<AskDO> prevNextAskDetails(Long askId) {
		return this.askDAO.prevNextAskDetails(askId);
	}
	
	@Override
	public List<AskDO> findUserVoteAsks(AskDO ask) {
		List<AskDO> asks =new ArrayList<AskDO>();
		UserDO user=this.userDAO.getUserById(ask.getUserId());
		List<AnswerVoteDO> votes =this.answerVoteDAO.findUserVotes(ask);
		for(AnswerVoteDO vote:votes){
			AskDO queryAsk =this.askDAO.findAskByAskId(vote.getAskId());
			if(queryAsk!=null){
				AnswerDO answerQuery = new AnswerDO();
				answerQuery.setAskId(ask.getId());
				List<AnswerDO> answerList = this.answerBO.findAnswers(answerQuery, null);
				for(AnswerDO answer:answerList){
					if(answer.getId().equals(queryAsk.getId())){
						queryAsk.setAnswer(answer);
					}
				}
				// pad comments
				CommentDO commentQuery = new CommentDO();
				commentQuery.setAskId(queryAsk.getId());
				List<CommentDO> comments = commentBO.findAskComments(commentQuery);
				queryAsk.setCommentList(comments);
				queryAsk.setUserName(user.getNickname());
				queryAsk.setAvatarPath(user.getAvatarPath());
				asks.add(queryAsk);
				
			}
		}
		return asks;
	}
	@Override
	public List<AskDO> findUserLikeAsks(AskDO ask) {
		List<Long> askIds=this.likeDAO.findUserLikeAskIds(ask);
		List<AskDO> asks=this.askDAO.findAskListByIds(askIds);
		return padAsk(asks, ask.getUserId());
	}
	
	@Override
	public List<AskDO> findTop5VoteOrLikeAsk(String orderBy) {
		return askDAO.findTop5Ask(orderBy);
	}
	
	public void setAskDAO(AskDAO askDAO) {
		this.askDAO = askDAO;
	}

	public void setUserDAO(UserDAO userDAO) {
		this.userDAO = userDAO;
	}

	public void setFollowDAO(FollowDAO followDAO) {
		this.followDAO = followDAO;
	}

	public void setCommentDAO(CommentDAO commentDAO) {
		this.commentDAO = commentDAO;
	}

	public void setAnswerDAO(AnswerDAO answerDAO) {
		this.answerDAO = answerDAO;
	}

	public void setAnswerVoteDAO(AnswerVoteDAO answerVoteDAO) {
		this.answerVoteDAO = answerVoteDAO;
	}

	public void setAnswerBO(AnswerBO answerBO) {
		this.answerBO = answerBO;
	}

	public void setLikeDAO(LikeDAO likeDAO) {
		this.likeDAO = likeDAO;
	}

	public void setCommentBO(CommentBO commentBO) {
		this.commentBO = commentBO;
	}
}
